import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;

public class SpreadsheetPanel extends JPanel {
   JTable table;
   TableModel model = new SpreadsheetModel();

   public SpreadsheetPanel() {
      table = new JTable(model);
     table.setDefaultRenderer(Object.class, new FastStringRenderer());
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
      table.setCellSelectionEnabled(true);
      JScrollPane scroller = new JScrollPane(table);
      scroller.setRowHeaderView(new SpreadsheetRowHeader(table));      
      setLayout(new BorderLayout());
      add(scroller, BorderLayout.CENTER);
      JMenuItem scroll = new JMenuItem("Scroll");
      scroll.addActionListener(new ActionListener(){
                               public void actionPerformed(ActionEvent e){
                               runScrollTest();}});
      JMenuItem populate = new JMenuItem("Populate");
      populate.addActionListener(new ActionListener(){
                                 public void actionPerformed(ActionEvent e){
                                 populate();}});

      JMenu test = new JMenu("Test");
      test.add(scroll);
      test.add(populate);

      JMenuBar mb = new JMenuBar();
      mb.add(test);
      add(mb, BorderLayout.NORTH);
   }

   public void runScrollTest() {
      new ScrollThread().start();

   }

   public void populate() {
      SpreadsheetModel model = new SpreadsheetModel();
      int rowCount = 200; // we're only going to populate the first 200
      int columnCount = 200;
      int counter = 0;
      for (int row = 0; row < rowCount; row++) {
         for (int col = 0; col < columnCount; col++) {
            counter++;
          // if (counter % 3 == 0) {
               model.setValueAt(String.valueOf(counter), row, col);
               // System.out.println(row +","+col);
           // }
         }
      }
      this.model = model;
      table.setModel(model);
      table.repaint();
   }

   // =======================
   // Benchmark machinery
   //========================
   public static void rest() {
      Thread.yield();
      try {
         SwingUtilities.invokeAndWait(NullRunnable.singleton);         
      } catch (Exception e) {
         System.out.println( "failed resting " + e);
      }
      Toolkit.getDefaultToolkit().sync();
   }

   class ScrollThread extends Thread {
      public void run() {
         Stopwatch timer = new Stopwatch();

         ScrollRunnable scroller = new ScrollRunnable();
         for (int repeat = 0; repeat < 10; repeat++) {
            timer.start();
            for (int row =0; row < 200; row++) {
               scroller.index = row;
               SwingUtilities.invokeLater(scroller);
               rest();
            }
            timer.stop();
            System.out.println("Scrolltime = " + timer.getElapsedTime());
            timer.reset();

         }

      }
   }

   class ScrollRunnable implements Runnable {
      int index = 0;
      public void run() {
         Rectangle cellBound = table.getCellRect(index, 
                                                 0,
                                                 true);
         table.scrollRectToVisible(cellBound);
      }
   }
}

class NullRunnable implements Runnable {
   static NullRunnable singleton = new NullRunnable();
   public void run() {
   }
}


